package com.reactim.message.config.validation;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import com.reactim.message.config.ReactimConfig;
import com.reactim.message.config.PerformanceTestConfig;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validator;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 配置管理服务
 * 提供配置监控、健康检查、动态刷新等功能
 */
@Service
@Slf4j
public class ConfigurationManagementService {
    
    @Autowired
    private ReactimConfig reactimConfig;
    
    @Autowired
    private PerformanceTestConfig performanceTestConfig;
    
    @Autowired
    private Validator validator;
    
    @Autowired
    private Environment environment;
    
    @Autowired
    private ConfigurationHealthChecker healthChecker;
    
    private final Map<String, ConfigurationSnapshot> configurationHistory = new ConcurrentHashMap<>();
    private final Map<String, Integer> configurationUsageStats = new ConcurrentHashMap<>();
    private LocalDateTime lastHealthCheck = LocalDateTime.now();
    private ConfigurationHealthStatus currentHealthStatus = ConfigurationHealthStatus.UNKNOWN;
    
    /**
     * 定期执行配置健康检查
     */
    @Scheduled(fixedRate = 300000) // 每5分钟执行一次
    public void performScheduledHealthCheck() {
        try {
            log.debug("开始定期配置健康检查...");
            ConfigurationHealthResult result = performHealthCheck();
            
            if (result.hasErrors()) {
                log.error("配置健康检查发现错误: {}", result.getErrors());
                currentHealthStatus = ConfigurationHealthStatus.UNHEALTHY;
            } else if (result.hasWarnings()) {
                log.warn("配置健康检查发现警告: {}", result.getWarnings());
                currentHealthStatus = ConfigurationHealthStatus.WARNING;
            } else {
                log.debug("配置健康检查通过");
                currentHealthStatus = ConfigurationHealthStatus.HEALTHY;
            }
            
            lastHealthCheck = LocalDateTime.now();
            
        } catch (Exception e) {
            log.error("定期配置健康检查失败", e);
            currentHealthStatus = ConfigurationHealthStatus.ERROR;
        }
    }
    
    /**
     * 执行配置健康检查
     */
    public ConfigurationHealthResult performHealthCheck() {
        ConfigurationHealthResult result = new ConfigurationHealthResult();
        
        try {
            // 验证ReactIM配置
            validateReactimConfiguration(result);
            
            // 验证性能测试配置
            validatePerformanceTestConfiguration(result);
            
            // 检查配置一致性
            checkConfigurationConsistency(result);
            
            // 检查配置使用情况
            checkConfigurationUsage(result);
            
            // 检查环境特定配置
            checkEnvironmentSpecificConfiguration(result);
            
        } catch (Exception e) {
            result.addError("配置健康检查执行失败: " + e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 验证ReactIM配置
     */
    private void validateReactimConfiguration(ConfigurationHealthResult result) {
        Set<ConstraintViolation<ReactimConfig>> violations = validator.validate(reactimConfig);
        for (ConstraintViolation<ReactimConfig> violation : violations) {
            result.addError(String.format("ReactIM配置错误 [%s]: %s", 
                violation.getPropertyPath(), violation.getMessage()));
        }
        
        // 检查连接配置合理性
        ReactimConfig.ConnectionProperties connection = reactimConfig.getConnection();
        if (connection.getCleanupInterval() >= connection.getExpirationTime()) {
            result.addWarning("清理任务执行间隔大于等于连接过期时间，可能导致连接无法及时清理");
        }
        
        // 检查监控配置
        ReactimConfig.ConnectionProperties.MonitoringProperties monitoring = connection.getMonitoring();
        if (monitoring.getHeartbeatIntervalMs() * 3 > monitoring.getInactivityThresholdMs()) {
            result.addWarning("心跳检测间隔过长，可能导致不活跃连接检测不及时");
        }
        
        // 检查缓存配置
        ReactimConfig.ConnectionProperties.CacheProperties cache = connection.getCache();
        if (cache.isEnabled() && cache.getConnectionCacheMaxSize() < 1000) {
            result.addWarning(String.format("连接缓存容量较小(%d), 在高并发场景下可能影响性能", 
                cache.getConnectionCacheMaxSize()));
        }
        
        // 检查安全配置
        ReactimConfig.ConnectionProperties.SecurityProperties security = connection.getSecurity();
        if (security.isEnableEncryption() && !org.springframework.util.StringUtils.hasText(security.getEncryptionKey())) {
            result.addWarning("启用了数据加密但未设置加密密钥，将使用默认密钥（不推荐用于生产环境）");
        }
    }
    
    /**
     * 验证性能测试配置
     */
    private void validatePerformanceTestConfiguration(ConfigurationHealthResult result) {
        Set<ConstraintViolation<PerformanceTestConfig>> violations = validator.validate(performanceTestConfig);
        for (ConstraintViolation<PerformanceTestConfig> violation : violations) {
            result.addError(String.format("性能测试配置错误 [%s]: %s", 
                violation.getPropertyPath(), violation.getMessage()));
        }
        
        if (!performanceTestConfig.isValid()) {
            result.addError("性能测试配置无效，请检查所有必需的配置项");
        }
        
        // 检查测试配置的合理性
        if (performanceTestConfig.getMaxConnections() > 50000) {
            result.addWarning("最大连接数设置过高，可能导致系统资源不足");
        }
        
        if (performanceTestConfig.getOperationTimeoutSeconds() < 10) {
            result.addWarning("操作超时时间过短，可能导致测试不稳定");
        }
    }
    
    /**
     * 检查配置一致性
     */
    private void checkConfigurationConsistency(ConfigurationHealthResult result) {
        // 检查性能测试配置与主配置的一致性
        ReactimConfig.PerformanceProperties.TestProperties mainTestConfig = 
            reactimConfig.getPerformance().getTest();
        
        if (performanceTestConfig.getMaxConnections() != mainTestConfig.getMaxConnections()) {
            result.addWarning("性能测试配置中的最大连接数与主配置不一致");
        }
        
        if (performanceTestConfig.getOperationTimeoutSeconds() != mainTestConfig.getOperationTimeoutSeconds()) {
            result.addWarning("性能测试配置中的操作超时时间与主配置不一致");
        }
    }
    
    /**
     * 检查配置使用情况
     */
    private void checkConfigurationUsage(ConfigurationHealthResult result) {
        // 检查未使用的配置项
        List<String> unusedConfigs = findUnusedConfigurations();
        if (!unusedConfigs.isEmpty()) {
            result.addInfo("发现未使用的配置项: " + String.join(", ", unusedConfigs));
        }
        
        // 检查频繁访问的配置项
        List<String> frequentlyUsedConfigs = findFrequentlyUsedConfigurations();
        if (!frequentlyUsedConfigs.isEmpty()) {
            result.addInfo("频繁访问的配置项: " + String.join(", ", frequentlyUsedConfigs));
        }
    }
    
    /**
     * 检查环境特定配置
     */
    private void checkEnvironmentSpecificConfiguration(ConfigurationHealthResult result) {
        String[] activeProfiles = environment.getActiveProfiles();
        
        if (activeProfiles.length == 0) {
            result.addWarning("未设置活动配置文件，使用默认配置");
        } else {
            result.addInfo("当前活动配置文件: " + String.join(", ", activeProfiles));
        }
        
        // 检查生产环境特定配置
        if (Arrays.asList(activeProfiles).contains("prod")) {
            checkProductionConfiguration(result);
        }
        
        // 检查测试环境特定配置
        if (Arrays.asList(activeProfiles).contains("test")) {
            checkTestConfiguration(result);
        }
    }
    
    /**
     * 检查生产环境配置
     */
    private void checkProductionConfiguration(ConfigurationHealthResult result) {
        ReactimConfig.ConnectionProperties.SecurityProperties security = reactimConfig.getConnection().getSecurity();
        
        if (!security.isEnableEncryption()) {
            result.addWarning("生产环境建议启用数据加密");
        }
        
        if (!security.isEnableValidation()) {
            result.addWarning("生产环境建议启用连接验证");
        }
        
        if (security.getMaxConnectionsPerUser() > 10) {
            result.addWarning("生产环境建议限制每个用户的最大连接数");
        }
    }
    
    /**
     * 检查测试环境配置
     */
    private void checkTestConfiguration(ConfigurationHealthResult result) {
        ReactimConfig.ConnectionProperties.MonitoringProperties monitoring = reactimConfig.getConnection().getMonitoring();
        
        if (monitoring.isSendActualHeartbeat()) {
            result.addInfo("测试环境可以考虑禁用实际心跳发送以提高测试速度");
        }
        
        if (performanceTestConfig.getMaxConnections() > 10000) {
            result.addInfo("测试环境建议降低最大连接数以节省资源");
        }
    }
    
    /**
     * 记录配置使用情况
     */
    public void recordConfigurationUsage(String configPath) {
        configurationUsageStats.merge(configPath, 1, Integer::sum);
    }
    
    /**
     * 创建配置快照
     */
    public void createConfigurationSnapshot(String snapshotName) {
        ConfigurationSnapshot snapshot = new ConfigurationSnapshot(
            snapshotName,
            LocalDateTime.now(),
            reactimConfig,
            performanceTestConfig
        );
        configurationHistory.put(snapshotName, snapshot);
        log.info("创建配置快照: {}", snapshotName);
    }
    
    /**
     * 获取配置健康状态
     */
    public ConfigurationHealthStatus getCurrentHealthStatus() {
        return currentHealthStatus;
    }
    
    /**
     * 获取最后健康检查时间
     */
    public LocalDateTime getLastHealthCheckTime() {
        return lastHealthCheck;
    }
    
    /**
     * 获取配置使用统计
     */
    public Map<String, Integer> getConfigurationUsageStats() {
        return new HashMap<>(configurationUsageStats);
    }
    
    /**
     * 获取配置历史快照
     */
    public Map<String, ConfigurationSnapshot> getConfigurationHistory() {
        return new HashMap<>(configurationHistory);
    }
    
    /**
     * 查找未使用的配置项
     */
    private List<String> findUnusedConfigurations() {
        // 这里可以实现更复杂的逻辑来检测未使用的配置项
        List<String> unused = new ArrayList<>();
        
        // 示例：检查一些常见的可能未使用的配置
        if (configurationUsageStats.getOrDefault("reactim.connection.security.encryption-key", 0) == 0) {
            unused.add("reactim.connection.security.encryption-key");
        }
        
        return unused;
    }
    
    /**
     * 查找频繁使用的配置项
     */
    private List<String> findFrequentlyUsedConfigurations() {
        return configurationUsageStats.entrySet().stream()
                .filter(entry -> entry.getValue() > 100) // 使用次数超过100次
                .map(Map.Entry::getKey)
                .sorted()
                .toList();
    }
    
    /**
     * 配置健康检查结果
     */
    public static class ConfigurationHealthResult {
        private final List<String> errors = new ArrayList<>();
        private final List<String> warnings = new ArrayList<>();
        private final List<String> info = new ArrayList<>();
        
        public void addError(String error) {
            errors.add(error);
        }
        
        public void addWarning(String warning) {
            warnings.add(warning);
        }
        
        public void addInfo(String info) {
            this.info.add(info);
        }
        
        public List<String> getErrors() {
            return new ArrayList<>(errors);
        }
        
        public List<String> getWarnings() {
            return new ArrayList<>(warnings);
        }
        
        public List<String> getInfo() {
            return new ArrayList<>(info);
        }
        
        public boolean hasErrors() {
            return !errors.isEmpty();
        }
        
        public boolean hasWarnings() {
            return !warnings.isEmpty();
        }
        
        public boolean hasInfo() {
            return !info.isEmpty();
        }
    }
    
    /**
     * 配置快照
     */
    public static class ConfigurationSnapshot {
        private final String name;
        private final LocalDateTime timestamp;
        private final ReactimConfig reactimConfig;
        private final PerformanceTestConfig performanceTestConfig;
        
        public ConfigurationSnapshot(String name, LocalDateTime timestamp, 
                                   ReactimConfig reactimConfig, PerformanceTestConfig performanceTestConfig) {
            this.name = name;
            this.timestamp = timestamp;
            this.reactimConfig = reactimConfig;
            this.performanceTestConfig = performanceTestConfig;
        }
        
        public String getName() {
            return name;
        }
        
        public LocalDateTime getTimestamp() {
            return timestamp;
        }
        
        public ReactimConfig getReactimConfig() {
            return reactimConfig;
        }
        
        public PerformanceTestConfig getPerformanceTestConfig() {
            return performanceTestConfig;
        }
    }
    
    /**
     * 配置健康状态枚举
     */
    public enum ConfigurationHealthStatus {
        HEALTHY("健康"),
        WARNING("警告"),
        UNHEALTHY("不健康"),
        ERROR("错误"),
        UNKNOWN("未知");
        
        private final String description;
        
        ConfigurationHealthStatus(String description) {
            this.description = description;
        }
        
        public String getDescription() {
            return description;
        }
    }
}